             package com.java.diagnostics.visualizer.memory.parser;
             
             import com.java.diagnostics.visualizer.data.DataLevel;
             import com.java.diagnostics.visualizer.data.SourceData;
             import com.java.diagnostics.visualizer.data.StructuredData;
             import com.java.diagnostics.visualizer.data.StructuredDataBuilder;
             import com.java.diagnostics.visualizer.data.TupleDataBuilder;
             import com.java.diagnostics.visualizer.data.axes.AxisPair;
             import com.java.diagnostics.visualizer.data.axes.XDataAxis;
             import com.java.diagnostics.visualizer.data.axes.YDataAxis;
             import com.java.diagnostics.visualizer.exceptions.GCAndMemoryVisualizerException;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.factory.SourceDataFactory;
             import com.java.diagnostics.visualizer.impl.factory.LogFactory;
             import com.java.diagnostics.visualizer.memory.util.Messages;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableField;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableType;
             import com.java.diagnostics.visualizer.parser.vgc.sovereign.InstanceSovereignVGCParser;
             import com.java.diagnostics.visualizer.properties.OutputProperties;
             import com.java.diagnostics.visualizer.sources.Source;
             import java.io.BufferedReader;
             import java.text.MessageFormat;
             import java.util.HashMap;
             import java.util.HashSet;
             import java.util.Iterator;
             import java.util.Set;
             import java.util.logging.Level;
             import java.util.logging.Logger;
             import java.util.regex.Matcher;
             import java.util.regex.Pattern;
             
             public class InstanceSVMonParser
               extends NativeMemoryParser
             {
               private static final int MILLISECONDS_PER_SECOND = 1000;
               private static final String DASH = "-";
               public static final String COMMAND_TEMPLATE = "{0} command";
               private static final int KILOBYTES = 1024;
               private static final int MEGABYTES = 1048576;
               private static final int GIGABYTES = 1073741824;
               private static final int SHORT_PAGE_SIZE = 4096;
               private static final int MEDIUM_PAGE_SIZE = 65536;
               private static final int LARGE_PAGE_SIZE = 16777216;
               private static final int HUGE_PAGE_SIZE = 0;
               public static final String HEADER = "Vsid      Esid Type Description ";
               private static final String WHITESPACE = "\\s*";
               private static final String NUMBER = "([0-9][0-9]*)";
               private static final String BLANKABLE_NUMBER = "([0-9\\-][0-9]*)";
               private static final String ESID = "([0-9a-fA-F-])";
               private static final String SPURIOUS_ASTERISK = "[ *]";
               private static final String CHAR = "([a-zA-Z])";
               private static final String PSIZE = "([a-zA-Z-]m?)";
               private static final String HEX = "([0-9a-fA-F][0-9a-fA-F]*)";
               private static final String PROCESSNAME = "(\\S*)";
               private static final String SPACEY_ADDRESSY_STRING = "([a-zA-Z0-9][a-zA-Z0-9/,:()_= -]* ]*)";
               private static final Pattern LINE_PATTERN = Pattern.compile("\\s*([0-9a-fA-F][0-9a-fA-F]*)\\s*[ *]\\s*([0-9a-fA-F-])\\s*([a-zA-Z0-9][a-zA-Z0-9/,:()_= -]* ]*)\\s*([a-zA-Z-]m?)\\s*([0-9\\-][0-9]*)\\s*([0-9\\-][0-9]*)\\s*([0-9\\-][0-9]*)\\s*([0-9\\-][0-9]*)\\s*");
               
               private static final int VSID_POS = 1;
               
               private static final int ESID_POS = 2;
               
               private static final int SEGMENTTEXT_POS = 3;
               
               private static final int PAGESIZE_POS = 4;
               
               private static final int INUSE_POS = 5;
               
               private static final int PINNED_POS = 6;
               
               private static final int PAGESPACE_POS = 7;
               
               private static final int VIRTUAL_POS = 8;
               
               private static final Pattern PROCESS_PATTERN = Pattern.compile("\\s*([0-9][0-9]*)\\s*(\\S*)\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*([a-zA-Z])\\s*([a-zA-Z])\\s*([a-zA-Z])\\s*");
               
               private static final Pattern RANGE_PATTERN = Pattern.compile("\\s*Addr Range:\\s*(([0-9][0-9]*)..([0-9][0-9]*)(\\s*:\\s*([0-9][0-9]*)..([0-9][0-9]*))*)\\s*");
               
               private static final Pattern SOURCES_PATTERN = Pattern.compile("\\s*source\\(s\\)=(([0-9a-fA-F][0-9a-fA-F]*)(, ([0-9a-fA-F][0-9a-fA-F]*))*)\\s*");
               
               private static final Pattern INTERVAL_PATTERN = Pattern.compile(
                 "inte[r]*val\\s*=\\s*([0-9][0-9]*)", 2);
               
               private static final Pattern DATE_PATTERN = Pattern.compile("([0-9][0-9]*):([0-9][0-9]*):([0-9][0-9]*)\\s*([a-zA-Z])([a-zA-Z])([a-zA-Z])\\s*[0-9][0-9][0-9][0-9]");
               
               private static final Pattern SECONDS_PATTERN = Pattern.compile(
                 "timestamp\\s*=\\s*([0-9][0-9]*)", 2);
               
               private static final Logger TRACE = LogFactory.getTrace(InstanceSovereignVGCParser.class);
               
               private TupleDataBuilder inUseTuple;
               
               private TupleDataBuilder pinnedTuple;
               
               private TupleDataBuilder virtualTuple;
               
               private TupleDataBuilder reservedAddressTuple;
               
               private TupleDataBuilder pageSpaceTuple;
               
               private double runningVirtual = -1.0D;
               private double runningReserved = -1.0D;
               private double runningInuse = -1.0D;
               private double runningPinned = -1.0D;
               private double runningPageSpace = -1.0D;
               
               private double interval = -1.0D;
               
               private AxisPair pagesAxisPair;
               
               private double pageSize = 4096.0D;
               
               private PageSizeUnitConverter pageSizeConverter;
               
               private static final String AIX = "aix";
               
               private String currentVsid;
               
               private VsidInfo currentVsidInfo;
               
               private HashMap<String, VsidInfo> vsidInfoMap = new HashMap();
               private HashSet<String> sourcesSet = new HashSet();
               
               public SourceData parse(Source source, OutputProperties properties) throws GCAndMemoryVisualizerException
               {
                 TRACE.entering(this.className, "parse");
                 
                 this.isGoodData = false;
                 
                 initialiseTuples();
                 this.xAxis = NativeMemoryAxes.prepareXAxis(source, properties);
                 
                 YDataAxis memoryAxis = 
                   NativeMemoryAxes.preparePagesMemoryAxis(properties);
                 
                 this.pageSizeConverter = new PageSizeUnitConverter(4096);
                 memoryAxis.addUnitConverter(this.pageSizeConverter);
                 this.pagesAxisPair = factory.createAxisPair(this.xAxis, memoryAxis);
                 
                 this.inUseTuple = 
                   createTuple("NativeMemoryLabels.inuse", this.pagesAxisPair);
                 this.pinnedTuple = 
                   createTuple("NativeMemoryLabels.pinned", this.pagesAxisPair);
                 this.pageSpaceTuple = 
                   createTuple("NativeMemoryLabels.paging", this.pagesAxisPair);
                 this.virtualTuple = createTuple("NativeMemoryLabels.aix.virtual", this.pagesAxisPair);
                 this.reservedAddressTuple = 
                   createTuple("NativeMemoryLabels.reserved", this.pagesAxisPair);
                 
                 this.inUseTuple.setTupleMetaData(new TupleMetaData(TupleMetaData.TableType.ARITHMETIC, 
                   new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 this.pinnedTuple.setTupleMetaData(new TupleMetaData(TupleMetaData.TableType.ARITHMETIC, 
                   new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 this.pageSpaceTuple.setTupleMetaData(new TupleMetaData(TupleMetaData.TableType.ARITHMETIC, 
                   new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 this.virtualTuple.setTupleMetaData(new TupleMetaData(TupleMetaData.TableType.ARITHMETIC, 
                   new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 this.reservedAddressTuple.setTupleMetaData(new TupleMetaData(
                   TupleMetaData.TableType.ARITHMETIC, new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, 
                   TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 
                 StructuredData platform = hiddenFactory.createStructuredData("platform", 
                   "platform");
                 ((StructuredDataBuilder)platform).put("1", "aix");
                 try
                 {
                   String variantIdentifier = source.getVariantIdentifier();
                   this.sourceData = 
                     SOURCE_DATA_FACTORY.createSourceData(variantIdentifier);
                   
                   BufferedReader reader = source.getSafeBufferedStreamReader();
                   
                   String line = reader.readLine();
                   
                   while (line != null) {
                     handleLine(line, reader);
                     
                     line = reader.readLine();
                   }
                   
                   if (this.isGoodData)
                   {
                     addRunningTotalsToTuples();
                     
                     this.sourceData.addData(platform, DataLevel.VARIANT);
                     writeOutSourceData();
                   }
                   this.xAxis.updateNormalisation(this.sourceData);
                   reader.close();
                 } catch (Exception e) {
                   TRACE.log(Level.WARNING, e.toString(), e);
                   this.sourceData = null;
                 }
                 TRACE.exiting(this.className, "parse");
                 return this.sourceData;
               }
               
               private void handleLine(String line, BufferedReader reader)
               {
                 if (this.interval == -1.0D)
                 {
                   Matcher dateMatcher = DATE_PATTERN.matcher(line);
                   Matcher secondsMatcher = SECONDS_PATTERN.matcher(line);
                   if (dateMatcher.find()) {
                     this.runningTimestamp = AIXDateConverter.parseDate(line);
                   } else if (secondsMatcher.find()) {
                     this.runningTimestamp = (Long.parseLong(secondsMatcher.group(1)) * 1000L);
                   } else {
                     Matcher intervalLine = INTERVAL_PATTERN.matcher(line);
                     if (intervalLine.find()) {
                       this.interval = 
                         (1000.0D * Double.parseDouble(intervalLine.group(1)));
                     }
                   }
                 }
                 
                 Matcher processLine = PROCESS_PATTERN.matcher(line);
                 
                 if (processLine.matches())
                 {
                   addRunningTotalsToTuples();
                   
                   if (this.interval < 0.0D)
                   {
                     this.interval = 60000.0D;
                   }
                   this.runningTimestamp += this.interval;
                   
                   this.xAxis.setX(this.runningTimestamp);
                   this.isGoodData = true;
                   
                   String command = processLine.group(2);
                   this.sourceData.setVariantIdentifier(MessageFormat.format(
                     "{0} command", new String[] { command }));
                   
                   int pageSize = 4096;
                   if ("M".equals(processLine.group(9))) {
                     pageSize = 16777216;
                   }
                   
                   this.pageSizeConverter.setPageSize(pageSize);
                 }
                 else
                 {
                   Matcher reasonLine = LINE_PATTERN.matcher(line);
                   
                   if (reasonLine.matches()) {
                     String esid = reasonLine.group(2);
                     String pageSizeDescription = reasonLine.group(4);
                     this.pageSize = 4096.0D;
                     
                     if (esid.equals("0")) {
                       this.pageSize = 0.0D;
                     } else {
                       if ("m".equals(pageSizeDescription)) {
                         this.pageSize = 65536.0D;
                       } else if ("l".equalsIgnoreCase(pageSizeDescription)) {
                         this.pageSize = 16777216.0D;
                       } else if ("h".equals(pageSizeDescription)) {
                         this.pageSize = 0.0D;
                       } else if ("sm".equals(pageSizeDescription)) {
                         this.pageSize = 4096.0D;
                       }
                       
                       double inUse = this.pageSize * 
                         convertToNumber(reasonLine.group(5));
                       double pinned = this.pageSize * 
                         convertToNumber(reasonLine.group(6));
                       double pageSpace = this.pageSize * 
                         convertToNumber(reasonLine.group(7));
                       double virtual = this.pageSize * 
                         convertToNumber(reasonLine.group(8));
                       
                       if (esid.equals("-"))
                       {
                         this.currentVsidInfo = new VsidInfo();
                         this.currentVsidInfo.inUse = inUse;
                         this.currentVsidInfo.pageSpace = pageSpace;
                         this.currentVsidInfo.pinned = pinned;
                         this.currentVsidInfo.virtual = virtual;
                         
                         this.currentVsid = reasonLine.group(1);
                       } else {
                         this.runningInuse += inUse;
                         this.runningPinned += pinned;
                         this.runningPageSpace += pageSpace;
                         this.runningVirtual += virtual;
                         
                         this.currentVsidInfo = null;
                       }
                       
                     }
                     
                   }
                   else
                   {
                     Matcher rangeMatcher = RANGE_PATTERN.matcher(line);
                     if (rangeMatcher.matches()) {
                       String[] ranges = rangeMatcher.group(1).split(" : ");
                       double rangeTotal = 0.0D;
                       for (int i = 0; i < ranges.length; i++) {
                         String[] range = ranges[i].split("\\.\\.");
                         
                         if (range.length == 2) {
                           double rangeStart = Double.parseDouble(range[0]);
                           double rangeEnd = Double.parseDouble(range[1]);
                           rangeTotal += rangeEnd - rangeStart + 1.0D;
                         }
                       }
                       
                       if (this.currentVsidInfo == null) {
                         this.runningReserved += this.pageSize * rangeTotal;
                       } else {
                         this.currentVsidInfo.reserved = (this.pageSize * rangeTotal);
                         this.vsidInfoMap.put(this.currentVsid, this.currentVsidInfo);
                         this.currentVsidInfo = null;
                       }
                     }
                     
                     Matcher sourcesMatcher = SOURCES_PATTERN.matcher(line);
                     if (sourcesMatcher.matches()) {
                       String[] sources = sourcesMatcher.group(1).split(", ");
                       for (int i = 0; i < sources.length; i++) {
                         this.sourcesSet.add(sources[i]);
                       }
                     }
                   }
                 }
               }
               
               private void addRunningTotalsToTuples()
               {
                 Iterator<String> iter = this.sourcesSet.iterator();
                 while (iter.hasNext()) {
                   String source = (String)iter.next();
                   VsidInfo vsidInfo = (VsidInfo)this.vsidInfoMap.get(source);
                   if (vsidInfo != null) {
                     this.runningInuse += vsidInfo.inUse;
                     this.runningPinned += vsidInfo.pinned;
                     this.runningPageSpace += vsidInfo.pageSpace;
                     this.runningVirtual += vsidInfo.virtual;
                     this.runningReserved += vsidInfo.reserved;
                   }
                 }
                 this.vsidInfoMap.clear();
                 this.sourcesSet.clear();
                 
                 addTotalToTuple(this.runningReserved, this.reservedAddressTuple, this.currentComment);
                 this.runningReserved = -1.0D;
                 addTotalToTuple(this.runningInuse, this.inUseTuple, this.currentComment);
                 this.runningInuse = -1.0D;
                 addTotalToTuple(this.runningPinned, this.pinnedTuple, this.currentComment);
                 this.runningPinned = -1.0D;
                 addTotalToTuple(this.runningPageSpace, this.pageSpaceTuple, this.currentComment);
                 this.runningPageSpace = -1.0D;
                 addTotalToTuple(this.runningVirtual, this.virtualTuple, this.currentComment);
                 this.runningVirtual = -1.0D;
               }
               
               private static void addTotalToTuple(double runningTotal, TupleDataBuilder tuple, String comment)
               {
                 if (runningTotal >= 0.0D) {
                   tuple.addDataPoint(runningTotal, comment);
                 }
               }
               
               private double convertToNumber(String string) {
                 if ("-".equals(string)) {
                   return 0.0D;
                 }
                 return Double.parseDouble(string);
               }
               
               private TupleDataBuilder createTuple(String label, AxisPair axisPair) {
                 TupleDataBuilder tuple = factory.createTupleData(label, 
                   Messages.getString(label), axisPair);
                 this.allTuples.add(tuple);
                 
                 return tuple;
               }
               
               static class VsidInfo
               {
                 public double inUse;
                 public double pinned;
                 public double pageSpace;
                 public double virtual;
                 public double reserved;
               }
             }


